package com.example.juc;

import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

public class CompleteAbleFutureTest {

    public static void main(String[] args) throws InterruptedException, ExecutionException {

        test33();

        System.out.println("主线程执行完成");

        Thread.sleep(100000000);

    }

    /**
     * 任务线程执行，等待结果不阻塞
     * @throws InterruptedException
     */
    private static void test1() throws InterruptedException {
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            getThreadName("任务子线程");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 1;
        }).whenComplete((v,e)->{
            getThreadName("结果子线程");
            System.out.println("异常"+e);
            System.out.println("结果"+v);
        });
    }

    /**
     * 多任务做计算（任务结果相互依赖），等待结果不阻塞
     * @throws InterruptedException
     */
    private static void test2() throws InterruptedException {
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {

            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            getThreadName("任务子线程1");
            return 1;
        }).thenApplyAsync((v)->{

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            getThreadName("任务子线程2");
            return v+2;
        }).whenCompleteAsync((v,e)->{
            getThreadName("结果子线程");
            System.out.println("结果"+v);
        });
    }

    /**
     * 多任务做计算（任务结果相互依赖），等待结果不阻塞
     * @throws InterruptedException
     */
    private static void test22() throws InterruptedException {
        CompletableFuture.supplyAsync(() -> {
            getThreadName("任务子线程1");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            return 1;
        }).thenCompose(v-> CompletableFuture.supplyAsync(()->{
            getThreadName("任务子线程2");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            return v+3;
        })).whenCompleteAsync((v,e)->{
            getThreadName("结果子线程");
            System.out.println("结果"+v);
        });
    }

    /**
     * 多任务做计算（任务结果不相互依赖，结果最后统一计算），等待结果不阻塞
     * @throws InterruptedException
     */
    private static void test3() throws InterruptedException {
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {

            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            getThreadName("任务子线程1");
            return 1;
        }).thenCombine(CompletableFuture.supplyAsync(()->{
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            getThreadName("任务子线程2");
            return 2;
        }),(a,b)->{
            getThreadName("任务子线程2-combine---"+a+b);
            return a+b;
        }).thenCombine(CompletableFuture.supplyAsync(()->{
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            getThreadName("任务子线程3");
            return 4;
        }),(a,b)->{
            getThreadName("任务子线程3-combine---"+a+b);
            return a+b;
        }).thenCombine(CompletableFuture.supplyAsync(()->{
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            getThreadName("任务子线程4");
            return 4;
        }),(a,b)->{
            getThreadName("任务子线程4-combine---"+a+b);
            return a+b;
        }).whenComplete((v,e)->{
            getThreadName("任务子线程4-Complete");
            System.out.println(v);
        });
    }

    private static void test33() throws InterruptedException, ExecutionException {
        List<Integer> values= Arrays.asList(1,2,3,5,6,7,8);

        //开始异步任务
        List<CompletableFuture<Integer>> completableFutures = values.stream().map(value -> CompletableFuture.supplyAsync(() -> {
            sleep();
            getThreadName("计算线程："+value);
            return value;
        })).collect(Collectors.toList());

        CompletableFuture<Integer> completableFuture=completableFutures.get(0);

        //合并异步任务结果
        for (int i=1;i< completableFutures.size();i++){
            completableFuture = completableFuture.thenCombine(completableFutures.get(i), (a, b) -> {
                sleep();
                getThreadName("统计线程："+a+b);
                System.out.println("计算"+a+b);
                return a+b;
            });
        }

       completableFuture.whenComplete((v,e)->{
           System.out.println("最后结果:"+v);
       });
    }

    private static void getThreadName(String taskName){
        System.out.println(taskName+"线程名字"+Thread.currentThread().getName());
    }

    private static void sleep(){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
